/**
 *
 * © Bahadir Zeren 2011
 * bzeren@gmail.com
 * No warranties, express or implied, are made for this program.
 *
 */

package org.baatar.opt.genetic.selection;

import org.baatar.opt.genetic.chromosome.IChromosome;
import org.baatar.util.RandomUtil;

/**
 * Binary tournament selection implementation of the ISelection interface.
 * 
 * @see ISelection
 */
public class BinaryTournamentSelection<T, M> implements ISelection<T, M> {

    /**
     * {@inheritDoc}
     */
    @Override
    public IChromosome<T, M> selectChromosomeForReproduction(IChromosome<T, M>[] population,
                                                                int range,
                                                                RandomUtil random) {

        IChromosome<T, M> c1 = population[random.getRandNumber(range)];
        IChromosome<T, M> c2 = population[random.getRandNumber(range)];

        while ((c1 == c2) || c1.isEqual(c2))
            c2 = population[random.getRandNumber(range)];

        if (c1.getFitness() < c2.getFitness())
            return c1;
        else
            return c2;

    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void replaceChromosomeForSurvival(IChromosome<T, M>[] population,
                                                int rangeStart,
                                                int rangeEnd,
                                                RandomUtil random) {

        int range = rangeEnd - rangeStart;

        if (range > 1) {
            int firstCandidateIndex = rangeStart + random.getRandNumber(range);
            IChromosome<T, M> c1 = population[firstCandidateIndex];

            int secondCandidateIndex = rangeStart + random.getRandNumber(range);
            while (firstCandidateIndex == secondCandidateIndex) {
                secondCandidateIndex = rangeStart + random.getRandNumber(range);
            }
            IChromosome<T, M> c2 = population[secondCandidateIndex];

            if (c1.getFitness() < c2.getFitness()) {
                c2 = population[rangeStart];
                population[rangeStart] = c1;
                population[firstCandidateIndex] = c2;
            } else {
                c1 = population[rangeStart];
                population[rangeStart] = c2;
                population[secondCandidateIndex] = c1;
            }
        }


//        if (chromosomeList.size() == 1)
//            return 0;
//
//        int firstCandidateIndex = random.getRandNumber(chromosomeList.size());
//        IChromosome<T, M> c1 = chromosomeList.get(firstCandidateIndex);
//
//        int secondCandidateIndex = random.getRandNumber(chromosomeList.size());
//        while (firstCandidateIndex == secondCandidateIndex) {
//            secondCandidateIndex = random.getRandNumber(chromosomeList.size());
//        }
//        IChromosome<T, M> c2 = chromosomeList.get(secondCandidateIndex);
//
//        if (c1.getFitness() < c2.getFitness())
//            return firstCandidateIndex;
//        else
//            return secondCandidateIndex;

    }

    /**
     * Clones the this object.
     * 
     * @return Object new cloned object.
     * 
     * @throws CloneNotSupportedException is trown if this object doesnt
     * implements Cloneable interface.
     */
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
